//! @file   lc_interval.cpp
//! @brief  
//! @author Sayan Chaliha
//! @date   September, 2011
//!
//! 
#include <lc_interval.h>
#include <lc_system.h>
#include <lc_numeric_limits.h>

namespace cyan {
    Interval::Interval() : interval_(0UL) {
    }
    
    Interval::Interval(const Interval& other) : interval_(other.interval_) {
    }
    
    Interval::Interval(ReservedInterval reservedInterval) {
        switch (reservedInterval) {
            case Interval::NOW:
                this->setToNow();
                break;
                
            case Interval::NO_WAIT:
                this->interval_ = 0UL;
                break;
                
            case Interval::NO_TIMEOUT:
                // Using NumericLimits<Clock>::maximum(), as should have been
                // the case here, causes overflow when converting to timeval or
                // timespec.
                this->interval_ = NumericLimits<Time>::maximum();
                break;
        }
    }
    
    Interval::Interval(const IntervalTime& ticks) : interval_(ticks) {
    }
    
    void Interval::setToNow() {
        this->interval_ = Interval::now();
    }
    
    Time Interval::toSeconds() const {
        return implicit_cast<Time>(this->interval_ / System::ticksPerSecond());
    }
    
    Time Interval::toMilliseconds() const {
        return implicit_cast<Time>(this->toSeconds() *
                                    MILLISECONDS_PER_SECOND);
    }
    
    Time Interval::toMicroseconds() const {
        return implicit_cast<Time>(this->toSeconds() *
                                    MICROSECONDS_PER_SECOND);
    }
    
    Time Interval::toSeconds(IntervalTime ticks) {
        return implicit_cast<Time>(ticks / System::ticksPerSecond());
    }
    
    Time Interval::toMilliseconds(IntervalTime ticks) {
        return implicit_cast<Time>(Interval::toSeconds(ticks) *
                                    MILLISECONDS_PER_SECOND);
    }
    
    Time Interval::toMicroseconds(IntervalTime ticks) {
        return implicit_cast<Time>(Interval::toSeconds(ticks) *
                                    MICROSECONDS_PER_SECOND);
    }
    
    Interval Interval::fromSeconds(Time seconds) {
        return IntervalTime(seconds * System::ticksPerSecond());
    }
    
    Interval Interval::fromMilliseconds(Time milliseconds) {
        return IntervalTime(milliseconds / MILLISECONDS_PER_SECOND *
                            System::ticksPerSecond());
    }
    
    Interval Interval::fromMicroseconds(Time microseconds) {
        return IntervalTime(microseconds / MICROSECONDS_PER_SECOND *
                            System::ticksPerSecond());
    }
    
    IntervalTime Interval::now() {
        return ::clock();
    }

    Interval Interval::operator -(const Interval& interval) const {
        return this->interval_ - interval.interval_;
    }

    Interval Interval::operator +(const Interval& interval) const {
        return this->interval_ + interval.interval_;
    }
    
    Interval Interval::operator /(const Interval& interval) const {
        return this->interval_ / interval.interval_;
    }
    
    Interval Interval::operator *(const Interval& interval) const {
        return this->interval_ * interval.interval_;
    }
    
    Interval& Interval::operator =(const Interval& interval) {
        this->interval_ = interval.interval_;
        return *this;
    }
    
    Interval& Interval::operator =(const IntervalTime& interval) {
        this->interval_ = interval;
        return *this;
    }
    
    Interval& Interval::operator -=(const Interval& interval) {
        this->interval_ -= interval.interval_;
        return *this;
    }
    
    Interval& Interval::operator +=(const Interval& interval) {
        this->interval_ += interval.interval_;
        return *this;
    }
    
    Interval& Interval::operator /=(const Interval& interval) {
        this->interval_ /= interval.interval_;
        return *this;
    }
    
    Interval& Interval::operator *=(const Interval& interval) {
        this->interval_ *= interval.interval_;
        return *this;
    }
    
    Bool Interval::operator <(const Interval& interval) const {
        return this->interval_ < interval.interval_;
    }
    
    Bool Interval::operator >(const Interval& interval) const {
        return this->interval_ > interval.interval_;
    }
    
    Bool Interval::operator <=(const Interval& interval) const {
        return this->interval_ <= interval.interval_;
    }
    
    Bool Interval::operator >=(const Interval& interval) const {
        return this->interval_ >= interval.interval_;
    }
    
    Bool Interval::operator ==(const Interval& interval) const {
        return this->interval_ == interval.interval_;
    }
    
    Bool Interval::operator !=(const Interval& interval) const {
        return this->interval_ != interval.interval_;
    }
    
    Interval::operator IntervalTime() const {
        return this->interval_;
    }
    
    IntervalTime operator -(const IntervalTime& lhs, const Interval& rhs) {
        return lhs - rhs.interval_;
    }
    
    IntervalTime operator +(const IntervalTime& lhs, const Interval& rhs) {
        return lhs + rhs.interval_;
    }
    
    IntervalTime operator /(const IntervalTime& lhs, const Interval& rhs) {
        return lhs / rhs.interval_;
    }
    
    IntervalTime operator *(const IntervalTime& lhs, const Interval& rhs) {
        return lhs * rhs.interval_;
    }
    
    IntervalTime& operator -=(IntervalTime& lhs, const Interval& rhs) {
        lhs -= rhs.interval_;
        return lhs;
    }
    
    IntervalTime& operator +=(IntervalTime& lhs, const Interval& rhs) {
        lhs += rhs.interval_;
        return lhs;
    }
    
    IntervalTime& operator /=(IntervalTime& lhs, const Interval& rhs) {
        lhs /= rhs.interval_;
        return lhs;
    }
    
    IntervalTime& operator *=(IntervalTime& lhs, const Interval& rhs) {
        lhs *= rhs.interval_;
        return lhs;
    }
    
    Bool operator <(const IntervalTime& lhs, const Interval& rhs) {
        return lhs < rhs.interval_;
    }
    
    Bool operator >(const IntervalTime& lhs, const Interval& rhs) {
        return lhs > rhs.interval_;
    }
    
    Bool operator <=(const IntervalTime& lhs, const Interval& rhs) {
        return lhs <= rhs.interval_;
    }
    
    Bool operator >=(const IntervalTime& lhs, const Interval& rhs) {
        return lhs >= rhs.interval_;
    }
    
    Bool operator ==(const IntervalTime& lhs, const Interval& rhs) {
        return lhs == rhs.interval_;
    }
    
    Bool operator !=(const IntervalTime& lhs, const Interval& rhs) {
        return lhs != rhs.interval_;
    }
}
